package com.love.cloud.gateway.filter;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.love.cloud.common.core.util.R;
import com.love.cloud.gateway.config.GatewayConfigProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;


@Component
@RefreshScope
public class TokenFilter implements GlobalFilter, Ordered {
    public static List<String> regexList = null;
    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    private  ObjectMapper objectMapper;
    @Resource
    private GatewayConfigProperties gatewayConfigProperties;

    /**
     * 可以用于验证用户登录状态，设置某部分请求信息等。
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String apiPath=request.getPath().toString();

        //如果不是GET请求，判断是否已经登录，token是否过期
        //获取cookie中的token令牌
        HttpHeaders headers = exchange.getRequest().getHeaders();
//        List<HttpCookie> cookies = multiValueMap.get("token");

        if ( headers.size() != 0) {
            String token = headers.getFirst("Authorization");
            //token 不为空 放行
            if (StringUtils.isNotBlank(token)) {
                return chain.filter(exchange);
            }else{
                if(this.isAllow(apiPath)){
                    return chain.filter(exchange);
                }
            }
        }
        return response.writeWith(Mono.create(monoSink -> {
            try {
                byte[] bytes = objectMapper.writeValueAsBytes(R.failed("登录过期请先登录"));
                DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);

                monoSink.success(dataBuffer);
            } catch (JsonProcessingException jsonProcessingException) {
                monoSink.error(jsonProcessingException);
            }
        }));
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 正则匹配地址
     *
     * @param path
     * @return
     */
    private boolean isAllow(String path) {
        Pattern pattern = null;
        String orginalUrl = path.split("[?]")[0];
        for (String regex : getRegexList()) {
            pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
            if (pattern.matcher(orginalUrl).matches()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取正则匹配规则list
     *
     * @return
     */
    private List<String> getRegexList() {
        //第一次加载这个,以及配置修改的时候加载这个(这个还没法实现，只能每次都加载)

        if (regexList == null) {
            regexList = new ArrayList<String>();
        }else{
            return regexList;
        }
        for (String url : gatewayConfigProperties.getAllowPaths()) {
            StringBuilder regex = new StringBuilder("\\S*").append(url.replace("/**", "\\S*")).append("\\S*");
            regexList.add(regex.toString());
        }
        return regexList;
    }

    /**
     * 获取正则匹配规则list
     *
     * @return
     */
//    private List<String> getRegexList() {
//        //第一次加载这个,以及配置修改的时候加载这个(这个还没法实现，只能每次都加载)
//        List<String> regexList=null;
//        Object regexListJson = redisTemplate.opsForValue().get("regexList");
//        if (regexListJson == null) {
//            regexList = new ArrayList<String>();
//        }else{
//            regexList = JSON.parseObject((String)regexListJson,new TypeReference<ArrayList<String>>() {
//            });
//            return regexList;
//        }
//        for (String url : gatewayConfigProperties.getAllowPaths()) {
//            StringBuilder regex = new StringBuilder("\\S*").append(url.replace("/**", "\\S*")).append("\\S*");
//            regexList.add(regex.toString());
//        }
//        redisTemplate.opsForValue().set("regexList",JSON.toJSONString(regexList));
//        return regexList;
//    }
}
